package com.xs.tool.message;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

/// 排行榜
@Getter
public class Rank<T, V extends Number & Comparable<V>> {
    private final List<RankLine<T, V>> rank = new ArrayList<>();

    /// 添加数据
    public void addLine(T id, V value) {
        RankLine<T, V> line = new RankLine<>(id, 0, value);
        rank.add(line);
        rank.sort((a, b) -> b.getValue().compareTo(a.getValue()));
        for (RankLine<T, V> rankLine : rank) {
            rankLine.setIndex(rank.indexOf(rankLine) + 1);
        }
    }
    public void fullUpdateLine(T id, V value) {
        int rankPosition = findRankPosition(id);
        rank.remove(rankPosition);
        addLine(id, value);
    }

    /// 增加value
    public void addValue(T id, V value) {
        RankLine<T, V> line = new RankLine<>(id, 0, value);
        if (rank.contains(line)) {
            RankLine<T, V> rankLine = obTainRankLine(id);
            // 更新现有记录的值
            rankLine.addValue(value);
        } else {
            // 如果不存在，则添加新记录
            addLine(id, value);
        }
    }

    /// 获取指定位置的排行数据
    public RankLine<T, V> obTainRankLine(T id) {
        for (int i = 0; i < rank.size(); i++) {
            if (rank.get(i).getId().equals(id)) {
                RankLine<T, V> line = rank.get(i);
                line.setIndex(i + 1);
                return line;
            }
        }
        return null;
    }

    /// 查找指定id的排名位置（从0开始） 返回-1 代表未上榜
    public int findRankPosition(T target) {
        for (RankLine<T, V> tvRankLine : rank) {
            if (tvRankLine.getId().equals(target)) {
                return tvRankLine.getIndex();
            }
        }
        return -1; // 未找到
    }


    public RankLine<T, V> getRank(Integer no) {
        rank.sort((a, b) -> b.getValue().compareTo(a.getValue()));
        return rank.get(no - 1);
    }

    /// 清空排行榜
    public void clear() {
        rank.clear();
    }

    /// 排行榜数据
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class RankLine<T, V> {
        private T id;
        @EqualsAndHashCode.Exclude
        private Integer index;
        @EqualsAndHashCode.Exclude
        private V value;

        public void addValue(V value) {
            if (value == null) {
                return;
            }

            Number currentNum = (Number) this.value;
            Number addNum = (Number) value;

            // 统一转为 double 计算
            double sum = currentNum.doubleValue() + addNum.doubleValue();

            // 根据原始值的类型决定返回值类型
            switch (this.value) {
                case Integer ignored -> this.value = (V) Integer.valueOf((int) sum);
                case Long ignored -> this.value = (V) Long.valueOf((long) sum);
                case Float ignored -> this.value = (V) Float.valueOf((float) sum);
                case null, default ->
                    // 默认保留 double 类型
                        this.value = (V) Double.valueOf(sum);
            }
        }

    }
}
